import fs from 'fs';
import JSZip from 'jszip';
import { DOMParser } from 'xmldom';

/**
 * 提取 docx 文件中的批注、对应文字及所属词目原文内容
 * @param {string} filePath - .docx 文件路径
 * @returns {Promise<Array<{id, author, date, text, target, term, context}>>}
 */
async function extractCommentsWithTarget(filePath) {
  const data = fs.readFileSync(filePath);
  const zip = await JSZip.loadAsync(data);

  // === 1. 获取批注文件 ===
  const commentsFile = zip.file('word/comments.xml');
  if (!commentsFile) {
    console.log('该文件中没有批注');
    return [];
  }
  const commentsXml = await commentsFile.async('string');
  const commentsDoc = new DOMParser().parseFromString(commentsXml, 'text/xml');
  const commentNodes = commentsDoc.getElementsByTagName('w:comment');

  const commentsMap = {};
  for (let i = 0; i < commentNodes.length; i++) {
    const node = commentNodes[i];
    const id = node.getAttribute('w:id');
    const author = node.getAttribute('w:author');
    const date = node.getAttribute('w:date');
    const textNodes = node.getElementsByTagName('w:t');
    let text = '';
    for (let j = 0; j < textNodes.length; j++) text += textNodes[j].textContent;
    commentsMap[id] = { id, author, date, text: text.trim() };
  }

  // === 2. 解析正文 document.xml ===
  const docFile = zip.file('word/document.xml');
  if (!docFile) throw new Error('缺少 document.xml 文件');
  const docXml = await docFile.async('string');
  const docDom = new DOMParser().parseFromString(docXml, 'text/xml');
  const paragraphs = Array.from(docDom.getElementsByTagName('w:p'));

  // === 3. 构建一个按段落顺序的 runs 列表 ===
  const runs = [];
  paragraphs.forEach((p, pIndex) => {
    const rNodes = p.getElementsByTagName('w:r');
    for (let i = 0; i < rNodes.length; i++) {
      const r = rNodes[i];
      const textNode = r.getElementsByTagName('w:t')[0];
      const text = textNode ? textNode.textContent : '';

      // 关键点：检测是否加粗（包括嵌套的 <w:rPr><w:b/>）
      const isBold =
        r.getElementsByTagName('w:b').length > 0 ||
        (r.parentNode &&
          r.parentNode.getElementsByTagName('w:b').length > 0);

      const commentStart = r.getElementsByTagName('w:commentRangeStart')[0];
      const commentEnd = r.getElementsByTagName('w:commentRangeEnd')[0];

      runs.push({
        text,
        pIndex,
        isBold,
        commentStartId: commentStart
          ? commentStart.getAttribute('w:id')
          : null,
        commentEndId: commentEnd ? commentEnd.getAttribute('w:id') : null,
      });
    }
  });

  // === 4. 提取词目（加粗文本）===
  const terms = [];
  for (let i = 0; i < runs.length; i++) {
    if (runs[i].isBold && runs[i].text.trim()) {
      terms.push({ index: i, term: runs[i].text.trim() });
    }
  }

  // === 5. 记录批注文字与所在范围 ===
  const commentTexts = {};
  const commentPositions = {};
  let currentCommentId = null;
  let startIdx = null;
  let buffer = '';

  for (let i = 0; i < runs.length; i++) {
    const r = runs[i];
    if (r.commentStartId) {
      currentCommentId = r.commentStartId;
      startIdx = i;
      buffer = '';
    }
    if (currentCommentId) buffer += r.text;
    if (r.commentEndId && currentCommentId === r.commentEndId) {
      commentTexts[currentCommentId] = buffer.trim();
      commentPositions[currentCommentId] = { start: startIdx, end: i };
      currentCommentId = null;
      buffer = '';
    }
  }

  // === 6. 找出批注所在词目区间 ===
  const results = [];
  for (const id in commentsMap) {
    const pos = commentPositions[id];
    let term = '(未找到词目)';
    let context = '(未找到原文内容)';

    if (pos) {
      // 向前找到最近的加粗（词目开头）
      let termIdx = -1;
      for (let i = terms.length - 1; i >= 0; i--) {
        if (terms[i].index <= pos.start) {
          termIdx = i;
          break;
        }
      }

      if (termIdx >= 0) {
        term = terms[termIdx].term;
        const termStart = terms[termIdx].index;
        const termEnd =
          termIdx < terms.length - 1 ? terms[termIdx + 1].index : runs.length;

        context = runs
          .slice(termStart, termEnd)
          .map((r) => r.text)
          .join('')
          .replace(/\s+/g, ' ')
          .trim();
      }
    }

    results.push({
      ...commentsMap[id],
      target: commentTexts[id] || '(未找到对应文字)',
      term,
      context,
    });
  }

  return results;
}

// 示例调用
extractCommentsWithTarget('./demo.docx').then((comments) => {
  console.log('批注详情：');
  for (const c of comments) {
    console.log(`➡️ 批注ID ${c.id}`);
    console.log(`   作者：${c.author}`);
    console.log(`   时间：${c.date}`);
    console.log(`   词目：${c.term}`);
    console.log(`   被批注文字：${c.target}`);
    console.log(`   批注内容：${c.text}`);
    console.log(`   原文内容：${c.context}`);
    console.log('---');
  }
});
